#include "Qt3DPicker.h"
#include "QtOSGWidget.h"

#include "Stretch2DHandler.h"
#include "CmdManager.h"
#include "Scene.h"
#include "SendPointHandlerBase.h"
#include "SelectHandler3D.h"
#include "OSGNodeMask.h"
#include "OsgUtil.h"
#include "Operation/OpReplace.h"
#include "QtOSGWidget.h"

Stretch2DHandler::Stretch2DHandler()
{
}

Stretch2DHandler::~Stretch2DHandler()
{
}

void Stretch2DHandler::input(const QVariant& data, const QString& rawInput, CommandSource cs)
{
	auto scene = getScene();
	auto widget3D = getWidget();
	auto sph = getSendPointHandler();
	auto selector = qobject_cast<SelectHandler3D*>(getSelectHandler());
	if (data.type() == QVariant::Bool)
	{
		bool esc = !data.toBool();
		if (esc)
		{
			if (m_stretchDatas.size() > 0)
			{
				widget3D->pauseRenderThread();
				for (auto data : m_stretchDatas)
				{
					auto parent = data.clone->getParent();
					if (parent)
						parent->removeChild(data.clone);
				}
				widget3D->resumeRenderThread();
			}
			selector->clearSelection();
			clearInput();
			emit finished();
			return;
		}
	}

	if (status() == 0)
	{
		if (selector)
		{
			selector->clearSelection();
			selector->beginSelect(D2CurveMask);
			prompt(1, tr("选择对象: "));
		}
		else
		{
			emit finished();
		}
		return;
	}

	if (status() == 1)
	{
		if (selector && selector->done())
		{
			auto selections = selector->selectionSet();
			if (selections.size() > 0)
			{
				auto selection = *selections.begin();
				std::shared_ptr<Ent> ent = std::dynamic_pointer_cast<Ent>(selection);
				auto parent = ent->getParent();
				UCS* ucs = dynamic_cast<UCS*>(parent);
				if (ucs)
				{
					m_ucs = ucs;
				}
				else
				{
					remark(tr("请选择二维图形"));
					emit finished();
					return;
				}
				if (sph)
				{
					sph->setPointMask(CS_LBTNDOWN | CS_MOUSEMOVE);
				}
				enableMouseHandler(MouseHandlerID::PointSender);
				cmdManager()->setPlane((Plane2DKind)m_ucs->getKind());
				prompt(2, tr("选择夹点:"));
			}
		}
		return;
	}

	if (status() == 2)
	{
		if (data.type() == QVariant::Vector3D)
		{
			if (cs == CS_MOUSEMOVE)
				return;
			auto pt = data.value<QVector3D>();
			osg::Vec3d clickWorldPt = { pt.x(),pt.y(),pt.z() };
			osg::Vec3d ucspt;
			bool suc = getViewPointOnPlane(*m_ucs, clickWorldPt, ucspt);
			if (!suc)
				return; 
			m_start = m_end = ucspt;
			auto matrix = m_ucs->getMatrix();
			show3DRubberLine(true);
			set3DRubberLineP1(m_start * matrix);
			set3DRubberLineP2(m_end * matrix);
			auto widget3D = getWidget();
			auto viewer = dynamic_cast<ViewerExt *>(widget3D->getViewer());
			if (!viewer)
				return;
			auto camera = viewer->getCamera();
			if (camera)
			{
				osg::Matrix VPW, invVPW;
				bool success = getCameraViewProjectionWindowMatrix(camera, VPW, invVPW);
				if (!success)
					return;
				auto clickScreenPt = clickWorldPt * VPW;
				auto selections = selector->selectionSet();
				for (auto selection : selections)
				{
					std::shared_ptr<Ent> ent = std::dynamic_pointer_cast<Ent>(selection);
					auto parent = ent->getParent();
					UCS* ucs = dynamic_cast<UCS*>(parent);
					if (ucs != m_ucs)
						continue;
					auto points = ent->handles();
					StretchData data;
					for (int i = 0; i < points.size(); i++)
					{
						auto osgNode = ent->getRep3D();
						auto matrix = osgNode->getWorldMatrices()[0];
						osg::Vec3d worldpt = points[i] * matrix;
						auto handleScreenPt = worldpt * VPW;
						if (clickScreenPt.x() > handleScreenPt.x() - 10 && clickScreenPt.x() < handleScreenPt.x() + 10 &&
							clickScreenPt.y() > handleScreenPt.y() - 10 && clickScreenPt.y() < handleScreenPt.y() + 10)
						{
							data.handleIndexes.push_back(i);
						}
					}
					if (data.handleIndexes.size() > 0)
					{
						data.ent = ent;
						auto clone = ent->clone();
						if (parent)
						{
							widget3D->pauseRenderThread();
							parent->addChild(clone);
							widget3D->resumeRenderThread();
						}
						data.clone = clone;
						m_stretchDatas.push_back(data);
					}
				}
				if (m_stretchDatas.empty())
				{
					remark(tr("请选择同一平面的图形"));
					emit finished();
					return;
				}
				prompt(3, tr("指定终点:"));
			}
		}
		return;
	}

	if (status() == 3)
	{
		osg::Vec3d ucspt;
		if (getPoint2D(*m_ucs, data, rawInput, cs, ucspt))
		{ 
			osg::Vec3d m_end = ucspt;
			const osg::Vec3d offset = m_end - m_start;
			auto matrix = m_ucs->getMatrix();
			set3DRubberLineP2(m_end * matrix);

			if (cs == CS_MOUSEMOVE)
			{
				for (auto data : m_stretchDatas)
				{
					std::shared_ptr<Ent> clone = std::dynamic_pointer_cast<Ent>(data.clone);
					std::shared_ptr<Ent> ent = std::dynamic_pointer_cast<Ent>(data.ent);
					if (ent && clone)
					{
						clone->copy(*ent);
						for (auto index : data.handleIndexes)
						{
							clone->stretch(index, offset);
						}
					}
				}
			}
			else
			{
				std::vector<std::shared_ptr<Ent>> origins;
				std::vector<std::shared_ptr<Ent>> clones;
				for (auto data : m_stretchDatas)
				{
					std::shared_ptr<Ent> clone = std::dynamic_pointer_cast<Ent>(data.clone);
					std::shared_ptr<Ent> ent = std::dynamic_pointer_cast<Ent>(data.ent);
					if (ent && clone)
					{
						clone->copy(*ent);
						for (auto index : data.handleIndexes)
						{
							clone->stretch(index, offset);
						}
						origins.push_back(ent);
						clones.push_back(clone);
					}
				}
				// 记录下本次操作				
				auto undoStack = scene->undoStack();
				undoStack->push(new OpReplace(origins, clones));
				selector->clearSelection();
				emit finished();
			}
		}
		return;
	}
}